Powershell scripts/Enable Defender for SQL servers on machines/EnableDefenderForSqlOnMachines.ps1 (207 lines of code) (raw):

#Requires -Modules Az.Resources, Az.OperationalInsights, Az.Accounts, Az, Az.PolicyInsights, Az.Security <# .SYNOPSIS Enable Defender for SQL servers on machines. .DESCRIPTION This script enables Defender for SQL servers on machines at a subscription level. .PARAMETER SubscriptionId [Required] The Azure subscription ID that you want to enable Defender for SQL servers on machines for. .PARAMETER RegisterSqlVmAgnet [Required] A flag indicating whether to register the SQL VM Agent in bulk. For more information: https://learn.microsoft.com/en-us/azure/azure-sql/virtual-machines/windows/sql-agent-extension-manually-register-vms-bulk?view=azuresql .PARAMETER WorkspaceResourceId [Optional] The resource ID of the Log Analytics workspace, if you want to use a custom one and not the default one. .PARAMETER DataCollectionRuleResourceId [Optional] The resource ID of the data collection rule, if you want to use a custom one and not the default one. .PARAMETER UserAssignedIdentityResourceId [Optional] The resource ID of the user-assigned identity, if you want to use a custom one and not the default one. #> param( [Parameter(Mandatory=$true)] [string]$SubscriptionId, [Parameter(Mandatory=$true)] [bool]$RegisterSqlVmAgnet, [string]$WorkspaceResourceId, [string]$DataCollectionRuleResourceId, [string]$UserAssignedIdentityResourceId ) $policyDefinitionReferenceIdsDefault = @( "MDC_DfSQL_AddUserAssignedIdentity_VM", "MDC_DfSQL_DeployWindowsAMA_VM", "MDC_DfSQL_DeployMicrosoftDefenderForSQLWindowsAgent_VM", "MDC_DfSQL_DeployDefaultWorkspace", "MDC_DfSQL_AMA_DefaultPipeline_VM", "MDC_DfSQL_DeployWindowsAMA_Arc", "MDC_DfSQL_DeployMicrosoftDefenderForSQLWindowsAgent_Arc", "MDC_DfSQL_AMA_DefaultPipeline_Arc", "MDC_DfSQL_AMA_DefaultPipeline_DCRA_Arc" ) $policyDefinitionReferenceIdsCustom = @( "MDC_DfSQL_AddUserAssignedIdentity_VM", "MDC_DfSQL_DeployWindowsAMA_VM", "MDC_DfSQL_DeployMicrosoftDefenderForSQLWindowsAgent_VM", "MDC_DfSQL_AMA_UserWorkspacePipeline_VM", "MDC_DfSQL_DeployWindowsAMA_Arc", "MDC_DfSQL_DeployMicrosoftDefenderForSQLWindowsAgent_Arc", "MDC_DfSQL_AMA_UserWorkspacePipeline_Arc", "MDC_DfSQL_AMA_UserWorkspacePipeline_DCRA_Arc" ) $policyInitiativeNames = @{ "default" = "d7c3ea3a-edf3-4bd5-bd64-d5b635b05393" "custom" = "de01d381-bae9-4670-8870-786f89f49e26" } $defaultLocation = "eastus" $ErrorActionPreference = "Stop" # Function to assign policy initiative definition with parameters function AssignPolicyInitiative { param( [Parameter(Mandatory=$true)] [string]$SubscriptionId, [Parameter(Mandatory=$true)] [string]$PolicyInitiativeName, [Parameter(Mandatory=$true)] [string]$AssignmentName, [string]$WorkspaceResourceId ) $policySetDefinition = Get-AzPolicySetDefinition -Name $PolicyInitiativeName if($AssignmentName.Length -gt 63) { $AssignmentName = $AssignmentName.Substring(0, 63) } # Assign policy initiative definition $assignmentParams = @{ "PolicySetDefinition" = $policySetDefinition "Name" = $AssignmentName "PolicyParameterObject" = @{} } if ($WorkspaceResourceId) { if ($WorkspaceResourceId.StartsWith("/")) { $WorkspaceResourceId = $WorkspaceResourceId.Substring(1) } # Get the Log Analytics workspace $workspace = Get-AzOperationalInsightsWorkspace -ResourceGroupName ($WorkspaceResourceId -split '/')[3] -Name ($WorkspaceResourceId -split '/')[7] $assignmentParams["PolicyParameterObject"]["userWorkspaceResourceId"] = "/" + $WorkspaceResourceId $assignmentParams["PolicyParameterObject"]["workspaceRegion"] = $workspace.Location $assignmentParams["PolicyParameterObject"]["userWorkspaceId"] = $workspace.CustomerId if ($DataCollectionRuleResourceId) { $assignmentParams["PolicyParameterObject"]["bringYourOwnDcr"] = $true $assignmentParams["PolicyParameterObject"]["dcrResourceId"] = $DataCollectionRuleResourceId } } if ($UserAssignedIdentityResourceId) { $assignmentParams["PolicyParameterObject"]["bringYourOwnUserAssignedManagedIdentity"] = $true $assignmentParams["PolicyParameterObject"]["userAssignedIdentityResourceId"] = $UserAssignedIdentityResourceId } return New-AzPolicyAssignment @assignmentParams -Scope "/subscriptions/$SubscriptionId" -IdentityType "SystemAssigned" -Location $defaultLocation } function Get-SubscriptionIdFromWorkspaceResourceId { param( [Parameter(Mandatory=$true)] [string]$WorkspaceResourceId ) return ($WorkspaceResourceId -split '/')[2] } # Main script try { Write-Host "Connecting to Azure..." Connect-AzAccount Write-Host "Selecting Azure subscription $SubscriptionId..." # Select the subscription Select-AzSubscription -SubscriptionId $SubscriptionId # SQL VM bulk registration $bulkRegistration = $RegisterSqlVmAgnet $policyDefinitionReferenceIds = $policyDefinitionReferenceIdsDefault $policyAssignment = @{} Write-Host "Assigning policy initiative definition with parameters..." # Assign policy initiative definition with parameters if ($WorkspaceResourceId) { $policyAssignmentName = "Defender for SQL on SQL VMs and Arc-enabled SQL Servers- Custom" $policyAssignment = AssignPolicyInitiative -SubscriptionId $SubscriptionId -PolicyInitiativeName $policyInitiativeNames["custom"] -AssignmentName $policyAssignmentName -WorkspaceResourceId $WorkspaceResourceId $policyDefinitionReferenceIds = $policyDefinitionReferenceIdsCustom } else { $policyAssignmentName = "Defender for SQL on SQL VMs and Arc-enabled SQL Servers" $policyAssignment = AssignPolicyInitiative -SubscriptionId $SubscriptionId -PolicyInitiativeName $policyInitiativeNames["default"] -AssignmentName $policyAssignmentName } # Create custom role assignments $permissions = @( "92aaf0da-9dab-42b6-94a3-d43ce8d16293", # Log Analytics Contributor "9980e02c-c2be-4d73-94e8-173b1dc7cf3c", # Virtual Machine Contributor "749f88d5-cbae-40b8-bcfc-e573ddc772fa", # Monitoring Contributor "cd570a14-e51a-42ad-bac8-bafd67325302", # Azure Connected Machine Resource Administrator "b24988ac-6180-42a0-ab88-20f7382dd24c" # Contributor ) Write-Host "Setting role assignment to policy assignment's Managed Identity..." # Set role assignment to policy assignment's Managed Identity $permissions | Foreach-Object -Parallel { try { New-AzRoleAssignment -ObjectId $using:policyAssignment.Identity.PrincipalId -RoleDefinitionId $_ -Scope "/subscriptions/$using:SubscriptionId" } catch { Write-Host "Failed to assign role $_ to policy assignment's Managed Identity on subscription level." throw $_.Exception.Message } } # If the workspace is different from the subscription, assign roles to the policy assignment's Managed Identity on workspace level if($WorkspaceResourceId -and ((Get-SubscriptionIdFromWorkspaceResourceId -WorkspaceResourceId $WorkspaceResourceId) -ne $SubscriptionId)) { $permissions | Foreach-Object -Parallel { try { New-AzRoleAssignment -ObjectId $using:policyAssignment.Identity.PrincipalId -RoleDefinitionId $_ -Scope $using:WorkspaceResourceId } catch { Write-Host "Failed to assign role $_ to policy assignment's Managed Identity on workspace level." throw $_.Exception.Message } } } # Create and run remediation step Write-Host "Creating and running remediation steps..." $remediationSuccess = $true $exceptionMessage = "" $policyDefinitionReferenceIds | Foreach-Object -Parallel { try { $remediationParams = @{ "PolicyAssignmentId" = $using:policyAssignment.PolicyAssignmentId "Name" = "Remediation-$_" "Scope" = "/subscriptions/$using:SubscriptionId" "ResourceDiscoveryMode" = "ReEvaluateCompliance" "PolicyDefinitionReferenceId" = $_ } # Run remediation step Start-AzPolicyRemediation @remediationParams } catch { Write-Host "Failed to create and run remediation step for policy assignment $policyAssignmentName. Exception: $($_.Exception.Message)" $remediationSuccess = $false $exceptionMessage = $_.Exception.Message } } if($remediationSuccess) { Write-Host "Remediation steps created and executed successfully." } else { throw $exceptionMessage } # Register SQL VMs for bulk registration / sql vm checkbox if ($bulkRegistration) { Write-Host "Registering SQL VMs for bulk registration..." try { $apiUrl = "https://management.azure.com/subscriptions/$SubscriptionId/providers/Microsoft.Features/providers/Microsoft.SqlVirtualMachine/features/BulkRegistration/register?api-version=2021-07-01" $accessToken = Get-AzAccessToken Invoke-RestMethod -Uri $apiUrl -Method Post -Headers @{"Authorization" = "Bearer $($accessToken.Token)"} } catch { Write-Host "Failed to register SQL VMs for bulk registration. Exception: $($_.Exception.Message)" throw $_.Exception.Message } } else { Write-Host "SQL VMs will not be registered for bulk registration." } # Turn on pricing bundle Write-Host "Turning on the pricing bundle..." Select-AzSubscription -SubscriptionId $SubscriptionId Set-AzSecurityPricing -Name SqlServerVirtualMachines -PricingTier Standard } catch { Write-Host "Failed to enable SQL ATP on-premises in scale. Exception: $($_.Exception.Message)" }